describe('Canlendar', function() {
    beforeEach(function() {
        expect(App.CalendarDataController).toBeDefined();
    });

    var givenMonthAndYear = function(month, year) {
        App.CalendarDataController.set('calendarMonth', month);
        App.CalendarDataController.set('calendarYear', year);            
    };

    describe('nextMonth', function() {
        beforeEach(function() {
            spyOn(App.CalendarDataController, 'populateCalendarMatrix');
        });

        
        it('next month of Jan. should be Feb. of same year', function() {
            givenMonthAndYear(0, 2013);

            App.CalendarDataController.nextMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2013, 1);
        });

        it('next month of Dec. should be Jan. of next year', function() {
            givenMonthAndYear(11, 2013);

            App.CalendarDataController.nextMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2014, 0);
        });

        it('next month of illegal larger month should be Jan. of next year', function() {
            givenMonthAndYear(12, 2013);

            App.CalendarDataController.nextMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2014, 0);
        });

        it('next month of illegal smaller month should be Jan. of same year', function() {
            givenMonthAndYear(-1, 2013);

            App.CalendarDataController.nextMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2013, 0);
        });

    });

    describe('prevMonth', function() {        
        beforeEach(function() {
            spyOn(App.CalendarDataController, 'populateCalendarMatrix');
        });

        
        it('previous month of Jan. should be Dec. of last year', function() {
            givenMonthAndYear(0, 2013);

            App.CalendarDataController.prevMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2012, 11);
        });

        it('previous month of Dec. should be Nov. of same year', function() {
            givenMonthAndYear(11, 2013);

            App.CalendarDataController.prevMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2013, 10);
        });

        it('previous month of illegal smaller month should be Dec. of last year', function() {
            givenMonthAndYear(-1, 2013);

            App.CalendarDataController.prevMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2012, 11);
        });

        it('previous month of illegal larger month should be Dec. of same year', function() {
            givenMonthAndYear(20, 2013);

            App.CalendarDataController.prevMonth();

            expect(App.CalendarDataController.populateCalendarMatrix).toHaveBeenCalledWith(2013, 11);
        });

    });

    describe('populateCalendarMatrix - adjust for leap year', function(){
        
        it('set valid year and month should be not changed', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(2013, 2);

            expect(App.CalendarDataController.get('calendarMonth')).toEqual(2);
            expect(App.CalendarDataController.get('calendarYear')).toEqual(2013);
        });

        it('set null year and month should get current year and month', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(null, null);

            expect(App.CalendarDataController.get('calendarMonth')).toEqual(3);
            expect(App.CalendarDataController.get('calendarYear')).toEqual(2013);
        });

        it('set invalid year and month should get NaN', function(){
            //TODO
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix('fdsafds', 'dfa');

            expect(isNaN(App.CalendarDataController.get('calendarMonth'))).toBeTruthy();
            expect(isNaN(App.CalendarDataController.get('calendarYear'))).toBeTruthy();
        });

        it('Feb of 2012 (leap year) should have 29 days', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(2012, 1);

            expect(App.CalendarDataController.get('monthDays')[1]).toEqual(29);
        });

        it('Feb of 2013 (non-leap year) should have 28 days', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(2013, 1);

            expect(App.CalendarDataController.get('monthDays')[1]).toEqual(28);
        });

        it('Feb of 1900 (non-leap year) should have 28 days', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(1900, 1);

            expect(App.CalendarDataController.get('monthDays')[1]).toEqual(28);
        });

        it('Feb of 2000 (leap year) should have 29 days', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 3, 8));

            App.CalendarDataController.populateCalendarMatrix(2000, 1);

            expect(App.CalendarDataController.get('monthDays')[1]).toEqual(29);
        });

    });

    describe('populateCalendarMatrix - populated dates array of Mar-2013', function(){
        beforeEach(function() {
            App.CalendarDataController.populateCalendarMatrix(2013, 2);
        });
        
        it('calendar of Mar-2013 should start from 24(Feb) and end at 6(Apr)', function(){
            expect(App.CalendarDataController.get('datesArr')[0][0].get('number')).toEqual(24);
            expect(App.CalendarDataController.get('datesArr')[5][6].get('number')).toEqual(6);
        });

        it('Feb and Apr dates in calendar of Mar-2013 are flagged as <outOfMonth>, while Mar dates are not', function(){
            expect(App.CalendarDataController.get('datesArr')[0][0].get('number')).toEqual(24);
            expect(App.CalendarDataController.get('datesArr')[0][0].get('isOutOfCurrentMonthDays')).toBeTruthy();
            expect(App.CalendarDataController.get('datesArr')[5][6].get('number')).toEqual(6);
            expect(App.CalendarDataController.get('datesArr')[5][6].get('isOutOfCurrentMonthDays')).toBeTruthy();
            expect(App.CalendarDataController.get('datesArr')[1][0].get('number')).toEqual(3);
            expect(App.CalendarDataController.get('datesArr')[1][0].get('isOutOfCurrentMonthDays')).toBeFalsy();
        });    

        it('Mar-12 is flagged as <today>, while others are not', function(){
            App.CalendarDataController.set('currentDate', new Date(2013, 2, 12));            

            App.CalendarDataController.populateCalendarMatrix(2013, 2);

            expect(App.CalendarDataController.get('datesArr')[2][2].get('number')).toEqual(12);
            expect(App.CalendarDataController.get('datesArr')[2][2].get('isToday')).toBeTruthy();
            expect(App.CalendarDataController.get('datesArr')[0][5].get('number')).toEqual(1);
            expect(App.CalendarDataController.get('datesArr')[0][5].get('isToday')).toBeFalsy();
        });    
    });

    describe('selectDate', function(){
        var spyTarget;

        beforeEach(function() {
            App.CalendarDataController.set('calendarYear', 2013);                
            App.CalendarDataController.set('calendarMonth', 2);
            spyTarget = jasmine.createSpyObj('target', ['selectCalendarDate']);
            App.CalendarDataController.set('target', spyTarget);
        });
        
        it('15-Mar-2013 is a flagged date then should be selected to the target', function(){
            var cell = App.CalendarCell.create({number:15, isCredit:true});
            App.CalendarDataController.set('flaggedDates', [new Date(2013, 2, 15)]);

            App.CalendarDataController.selectDate(cell);

            expect(spyTarget.selectCalendarDate).toHaveBeenCalledWith(new Date(2013, 2, 15), null);
        });

        it('15-Mar-2013 is not a flagged date then should 16-Mar-2013 (nearest) be selected to the target', function(){
            var cell = App.CalendarCell.create({number:15, isCredit:false});
            App.CalendarDataController.set('flaggedDates', [new Date(2013, 2, 14), new Date(2013, 2, 16)]);

            var selectedDate = new Date(2013, 2, 15);

            App.CalendarDataController.selectDate(cell);

            var error = BreezeException.create({errorCode:'', errorMessage: App.i18n.getTranslations().get('error.noRecords') + BreezeDateUtils.formatDateStyleddMMMyyyy(selectedDate)});

            expect(spyTarget.selectCalendarDate).toHaveBeenCalledWith(new Date(2013, 2, 16), error);
        });
    });

    describe('flagDate', function(){
        beforeEach(function() {
            // App.CalendarDataController.set('calendarMonth', 2);
            // spyTarget = jasmine.createSpyObj('target', ['selectCalendarDate']);
        });
        
        it('cell should be set flags if it is a flagged date', function(){
            var date = new Date(2013, 2, 15);
            App.CalendarDataController.set('detailedFlaggedDates', [{dateKey:'2013-3-15', isCredit:true, isDebit:true}]);                
            var cell = App.CalendarCell.create();
            var result = App.CalendarDataController.flagDate(date, cell);

            expect(result).toBeTruthy();
            expect(cell.get('isCredit')).toBeTruthy();
            expect(cell.get('isDebit')).toBeTruthy();
        });

        it('cell should not be set flags if it is not a flagged date', function(){
            var date = new Date(2013, 2, 15);
            App.CalendarDataController.set('detailedFlaggedDates', [{dateKey:'2013-3-16', isCredit:true}]);                
            var cell = App.CalendarCell.create();

            var result = App.CalendarDataController.flagDate(date, cell);

            expect(result).toBeFalsy();
            expect(cell.get('isCredit')).toBeFalsy();
            expect(cell.get('isDebit')).toBeFalsy();
        });

    });

});
